# coding: utf-8
from typing import Union

from qfluentwidgets import ImageLabel, FluentIconBase, FluentIcon as FIF, TransparentToolButton
from qtpy.QtCore import Qt, QSize, QBuffer, QIODevice, Signal, QObject
from qtpy.QtGui import QPixmap, QImage, QImageReader, QMovie, QPainter, QPainterPath, QColor, QIcon
from qtpy.QtNetwork import QNetworkReply
from qtpy.QtWidgets import QGraphicsDropShadowEffect, QLabel, QHBoxLayout, QFileDialog

from ....common import Translation, FileType, HTTPRequest, NetworkResponse


class ExpandImageLabel(ImageLabel):
    """ 拓展图像标签 """

    def _postInit(self):
        self.isPressed = False
        self.isHover = False

    def setImage(self, image: Union[str, QPixmap, QImage] = None):
        """
        设置图像
        :param image:
        :return:
        """
        self.image = image or QImage()

        if isinstance(image, str):
            reader = QImageReader(image)
            if reader.supportsAnimation():
                self.setMovie(QMovie(image))
            else:
                self.image = reader.read()
        elif isinstance(image, QPixmap):
            self.image = image.toImage()

        self.update()

    def enterEvent(self, e):
        self.isHover = True
        self.update()

    def leaveEvent(self, e):
        self.isHover = False
        self.update()

    def mousePressEvent(self, e):
        self.isPressed = True
        super().mousePressEvent(e)
        self.update()

    def mouseReleaseEvent(self, e):
        self.isPressed = False
        if e.button() == Qt.MouseButton.LeftButton:
            self.clicked.emit()
        QLabel.mouseReleaseEvent(self, e)
        self.update()

    def toByteArray(self):
        buffer = QBuffer()
        buffer.open(QIODevice.WriteOnly)
        self.image.save(buffer, "PNG")
        return buffer.data()

    def toBase64(self):
        return self.toByteArray().toBase64()

    def __onRequestFinished(self, response: NetworkResponse):
        self.setImage(response.image(FIF.GITHUB.value))
        response.deleteLater()

    def setUrl(self, url: str, headers: dict = None):
        HTTPRequest.get(url, headers=headers, response_callback=self.__onRequestFinished, parent=self)


class CenterImageLabel(ExpandImageLabel):
    """ 居中图像标签 """

    def paintEvent(self, e):
        if self.isNull():
            return

        painter = QPainter(self)
        painter.setRenderHints(QPainter.RenderHint.Antialiasing)

        # center crop image
        image = self.image.scaled(
            self.size() * self.devicePixelRatioF(),
            Qt.AspectRatioMode.KeepAspectRatioByExpanding,
            Qt.TransformationMode.SmoothTransformation
        )  # type: QImage

        iw, ih = image.width(), image.height()
        w = self.width() * self.devicePixelRatioF()
        h = self.height() * self.devicePixelRatioF()
        x, y = (iw - w) / 2, (ih - h) / 2
        image = image.copy(int(x), int(y), int(w), int(h))

        # draw image
        path = QPainterPath()
        w, h = self.width(), self.height()

        # top line
        path.moveTo(self.topLeftRadius, 0)
        path.lineTo(w - self.topRightRadius, 0)

        # top right arc
        d = self.topRightRadius * 2
        path.arcTo(w - d, 0, d, d, 90, -90)

        # right line
        path.lineTo(w, h - self.bottomRightRadius)

        # bottom right arc
        d = self.bottomRightRadius * 2
        path.arcTo(w - d, h - d, d, d, 0, -90)

        # bottom line
        path.lineTo(self.bottomLeftRadius, h)

        # bottom left arc
        d = self.bottomLeftRadius * 2
        path.arcTo(0, h - d, d, d, -90, -90)

        # left line
        path.lineTo(0, self.topLeftRadius)

        # top left arc
        d = self.topLeftRadius * 2
        path.arcTo(0, 0, d, d, -180, -90)

        painter.setPen(Qt.PenStyle.NoPen)
        painter.setClipPath(path)
        painter.drawImage(self.rect(), image)
        painter.end()


class ShadowLabelBase:
    """ 阴影标签基类 """

    def _postInit(self):
        super()._postInit()
        self.shadowEffect = QGraphicsDropShadowEffect(self)
        self.shadowEffect.setColor(QColor(0, 0, 0, 100))
        self.shadowEffect.setOffset(0, 0)
        self.shadowEffect.setBlurRadius(0)
        self.setGraphicsEffect(self.shadowEffect)

    def enterEvent(self, e):
        super().enterEvent(e)
        self.shadowEffect.setBlurRadius(30)

    def leaveEvent(self, e):
        super().leaveEvent(e)
        self.shadowEffect.setBlurRadius(0)

    def mousePressEvent(self, e):
        super().mousePressEvent(e)
        self.shadowEffect.setBlurRadius(10)

    def mouseReleaseEvent(self, e):
        super().mouseReleaseEvent(e)
        self.shadowEffect.setBlurRadius(30)


class ShadowImageLabel(ShadowLabelBase, ExpandImageLabel):
    """ 阴影图像标签 """


class ShadowCenterImageLabel(ShadowLabelBase, CenterImageLabel):
    """ 阴影居中图像标签 """

    def paintEvent(self, e):
        CenterImageLabel.paintEvent(self, e)


class EditableLabelBase:
    """ 可编辑图像标签 """
    deleteSignal = Signal(QObject)
    viewSignal = Signal(QImage)

    def _createButtons(self, icon: Union[QIcon, str, FluentIconBase]):
        button = TransparentToolButton(icon, self)
        button.setFixedSize(30, 30)
        button.setIconSize(QSize(16, 16))
        return button

    def _postInit(self):
        super()._postInit()

        self.horizontalLayout = QHBoxLayout(self)
        self.viewButton = self._createButtons(FIF.VIEW)
        self.editButton = self._createButtons(FIF.EDIT)
        self.deleteButton = self._createButtons(FIF.DELETE)

        self.horizontalLayout.addWidget(self.viewButton)
        self.horizontalLayout.addWidget(self.editButton)
        self.horizontalLayout.addWidget(self.deleteButton)

        self.viewButton.clicked.connect(lambda: self.viewSignal.emit(self.image))
        self.editButton.clicked.connect(self._editImage)
        self.deleteButton.clicked.connect(self._deleteImage)

    def setImage(self, image: Union[str, QPixmap, QImage] = None):
        super().setImage(image)
        self.__initButtonVisible()

    def _editImage(self):
        t = Translation()
        file, _ = QFileDialog.getOpenFileName(self, t.openFile, "", f"{t.imageFile} {FileType.IMAGE.toFilterString()};")
        if file:
            self.setImage(file)

    def _deleteImage(self):
        self.setImage(QImage())
        self.__initButtonVisible()
        self.deleteSignal.emit(self)

    def __initButtonVisible(self):
        visible = not self.image.isNull()
        self.viewButton.setVisible(visible)
        self.deleteButton.setVisible(visible)


class EditableImageLabel(EditableLabelBase, ExpandImageLabel):
    """ 可编辑图像标签 """


class EditableCenterImageLabel(EditableLabelBase, CenterImageLabel):
    """ 可编辑居中图像标签 """
